﻿#pragma once
#include <wrl.h>
#include "XamlSurfaceRenderer.h"
#include "Effect.h"

namespace XamlFx
{
    [Windows::Foundation::Metadata::WebHostHidden]
    public enum class RenderStrategy : int { RenderingEvent, Conservative, Manual};

    [Windows::Foundation::Metadata::WebHostHidden]
    public ref class ShaderContentControl sealed : public xaml::Controls::ContentControl
    {
    public:
        ShaderContentControl();
        virtual ~ShaderContentControl(void);
    public:
        DEPENDENCY_PROPERTY(Effect,               XamlFx::Effect^)
        DEPENDENCY_PROPERTY(EffectRenderStrategy, RenderStrategy)
        void InvalidateRaster();
        void Render();
    private:
        static void OnEffectChanged               (xaml::DependencyObject^ d, xaml::DependencyPropertyChangedEventArgs^ e);
        static void OnEffectRenderStrategyChanged (xaml::DependencyObject^ d, xaml::DependencyPropertyChangedEventArgs^ e);
    protected:                         
        virtual void OnContentChanged  (Platform::Object^ oldContent, Platform::Object^ newContent) override;
        virtual void OnApplyTemplate   () override;
    private:
        void OnDpiChanged              (display::DisplayInformation^sender, Platform::Object^e);
        void OnSuspending              (Platform::Object^sender, Windows::ApplicationModel::SuspendingEventArgs^args);
        void CompositionTargetRender   (Platform::Object^sender, Platform::Object^e);
        void OnLayoutUpdated           (Platform::Object^sender, Platform::Object^e);
        void OnSurfaceContentsLost     (Platform::Object^sender, Platform::Object^e);
        void OnLoaded                  (Platform::Object^sender, xaml::RoutedEventArgs^e);
        void OnUnloaded                (Platform::Object^sender, xaml::RoutedEventArgs^e);
        void SizeRenderedImage         (xaml::Thickness padding);
        void InitializeSurfaceRenderer (Dx::SizeU size);
        bool ShouldRender              ();
        bool ShouldReraster            ();
    private:
        XamlFx::RenderStrategy              m_renderStrategy;
        bool                                m_renderedElementDirty;
        bool                                m_ignoreNextLayoutUpdate;
        Dx::SizeF                           m_extraPadSize;
        std::atomic<bool>                   m_isRendering;
        GraphicsDeviceContextPtr            m_gfx;
        XamlSurfaceRenderer^                m_xamlSurfaceRenderer;
        xaml::UIElement^                    m_renderedElement;
        xaml::Controls::Image^              m_image;
        xaml::Controls::ContentPresenter^   m_contentShim;
        foundation::EventRegistrationToken  m_renderCallbackToken;
        foundation::EventRegistrationToken  m_loadedEventToken;
        foundation::EventRegistrationToken  m_unloadedEventToken;
        foundation::EventRegistrationToken  m_contentShimLayoutUpdated;
    };
}